#if  1

#include "gd32f30x.h"
#include "IO.h"
#include "BSP_Config.h"

#include "FreeRTOS.h"
#include "Task.h"

typedef struct SSPI {
	IO_T nss;
	IO_T sck;
	IO_T miso;
	IO_T mosi;
}SSPI_T;


static const SSPI_T sspi = {
	.nss = IO_INIT_TABLE(GPIOB, GPIO_PIN_0),
	.sck = IO_INIT_TABLE(GPIOA, GPIO_PIN_5),
	.miso = IO_INIT_TABLE(GPIOA, GPIO_PIN_6),
	.mosi = IO_INIT_TABLE(GPIOA, GPIO_PIN_7),
};

#define SPI_MOSI_SetState(spi, state) 	BSP_IO_Set((uint32_t)spi->mosi.port, spi->mosi.pin, state)
#define SPI_MISO_GetState(spi) 		BSP_IO_Get((uint32_t)spi->miso.port, spi->miso.pin)
#define SPI_CLK_SetState(spi, state) 	BSP_IO_Set((uint32_t)spi->sck.port, spi->sck.pin, state)

#define SSPI_DELAY_TIME		0

static inline void SSPI_Delay(const uint32_t count){
	uint32_t c = count;
	while(c != 0){
		--c;
	}
}

#define SPI_ExchangeBit(spi, send, receive, num) { \
	if((send) & (0x80 >> (num))){	SPI_MOSI_SetState(spi, 1u);} \
	else{SPI_MOSI_SetState(spi, 0u);} \
	SSPI_Delay(SSPI_DELAY_TIME);		\
	SPI_CLK_SetState(spi, 1);	\
	SSPI_Delay(SSPI_DELAY_TIME);		\
	if(SPI_MISO_GetState(spi)){(receive) |= (0x80 >> (num));}	\
	SSPI_Delay(SSPI_DELAY_TIME);		\
	SPI_CLK_SetState(spi, 0); \
	SSPI_Delay(SSPI_DELAY_TIME);		\
}

static void BSP_SSPI_DoInit(const SSPI_T* spi){
	IO_Init(&spi->nss, IO_Mode_OUT);
	IO_Init(&spi->sck, IO_Mode_OUT);
	IO_Init(&spi->miso, IO_Mode_IPU);
	IO_Init(&spi->mosi, IO_Mode_OUT);
}

void BSP_SPI_Init(uint8_t id, uint32_t freq){
	BSP_SSPI_DoInit(&sspi);
}

uint8_t BSP_SPI_Exchange(uint8_t id, uint8_t send){
    uint8_t rx = 0; 
	const uint8_t tx = send;
    const SSPI_T * spi = &sspi;
	
	taskENTER_CRITICAL();
    SPI_CLK_SetState(spi, 0);
	SPI_ExchangeBit(spi, tx, rx, 0);
	SPI_ExchangeBit(spi, tx, rx, 1);
	SPI_ExchangeBit(spi, tx, rx, 2);
	SPI_ExchangeBit(spi, tx, rx, 3);
	SPI_ExchangeBit(spi, tx, rx, 4);
	SPI_ExchangeBit(spi, tx, rx, 5);
	SPI_ExchangeBit(spi, tx, rx, 6);
	SPI_ExchangeBit(spi, tx, rx, 7);
	taskEXIT_CRITICAL();

    return rx;
}

void BSP_SPI_SetNSS(uint8_t id, uint8_t state){
    const SSPI_T * spi = &sspi;
	SSPI_Delay(5);
	IO_Set(&spi->nss, state);
	SSPI_Delay(5);
}

#endif

